package com.zlfund.cat.zjgsmk.util;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.LruCache;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import java.util.Queue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by chenj on 2017/9/4 0004.
 */

public class BitmapHelper {

    private static ExecutorService mThreadPool;
    private static LruCache<String, Bitmap> mLruCache;

    public static Bitmap scaleBm(Bitmap bm, int width, int height) {
        int bmWidth = bm.getWidth();
        int bmHeight = bm.getHeight();
        Matrix m = new Matrix();
        if (width * 1.0f / bmWidth > height * 1.0f / bmHeight) {
            m.postScale(width * 1.0f / bmWidth, width * 1.0f / bmWidth);
        } else {
            m.postScale(height * 1.0f / bmHeight, height * 1.0f / bmHeight);
        }
        //        Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
//        Canvas canvas = new Canvas(result);
//        canvas.draw
        return Bitmap.createBitmap(bm, 0, 0, bmWidth, bmHeight, m, false);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    public static Bitmap blur(Context context,Bitmap bkg, View view) {
        float radius = 20;

        Bitmap overlay = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(overlay);
        canvas.translate(-view.getLeft(), -view.getTop());
        canvas.drawBitmap(bkg, 0, 0, null);

        RenderScript rs = RenderScript.create(context);

        Allocation overlayAlloc = Allocation.createFromBitmap(rs, overlay);
        ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, overlayAlloc.getElement());
        blur.setInput(overlayAlloc);
        blur.setRadius(radius);
        blur.forEach(overlayAlloc);
        overlayAlloc.copyTo(overlay);
        rs.destroy();
        return overlay;
    }

    public static Bitmap cropCircleImage(Bitmap bm){
        int width = bm.getWidth();
        int height = bm.getHeight();
        int size = Math.min(width, height);
        Bitmap cropBm = Bitmap.createBitmap(bm, width / 2 - size / 2, height / 2 - size / 2, size, size);
        Bitmap result = Bitmap.createBitmap(size,size, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(result);
        Paint p = new Paint();
        p.setAntiAlias(true);
        c.drawCircle(size / 2,size / 2,size / 2,p);
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        c.drawBitmap(cropBm,0,0,p);
        return result;
    }

    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());
    }

    public static void setBitmap(final String path, final ImageView iv){
        iv.setTag(path);
        if (mThreadPool == null) {
            mThreadPool = new ThreadPoolExecutor(0, 6, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        }
        if (mLruCache == null){
            mLruCache = new LruCache<>(20 * 1024 * 1024);
        }
        if (mLruCache.get(path) == null){
            iv.setImageDrawable(new ColorDrawable(Color.LTGRAY));
        }
        Future<Bitmap> submit = mThreadPool.submit(new Callable<Bitmap>() {
            @Override
            public Bitmap call() throws Exception {
                if (mLruCache.get(path) == null){
                    Bitmap bm = compress(path, iv.getWidth(), iv.getHeight());
                    mLruCache.put(path, bm);
                    return bm;
                }
                return mLruCache.get(path);
            }
        });
        Observable.fromFuture(submit)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(Bitmap bitmap) throws Exception {
                        if (iv.getTag().equals(path)) {
                            iv.setImageBitmap(bitmap);
                        }
//                        Queue
                    }
                });
    }

    public static Bitmap compress(String path,int width, int height){
        long startTime = System.currentTimeMillis();
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path,options);
        options.inSampleSize = calculate(options,width,height);
        Logger.i("==============================================================");
        Logger.i("calculate time finish :   " + String.valueOf(System.currentTimeMillis() - startTime));
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        Logger.i("get bitmap finish :   " + String.valueOf(System.currentTimeMillis() - startTime));
        Logger.i("--------------------------------------------------------------");
        return bitmap;
    }

    private static int calculate(BitmapFactory.Options options, int width, int height) {
        int inSampleSize = 1;
        int bmWidth = options.outWidth;
        int bmHeight = options.outHeight;
        if (bmHeight > height || bmWidth > width){
            inSampleSize = 2;
            while (bmWidth / inSampleSize > width && bmHeight / inSampleSize > height){
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
}
